interface InteractElement extends Element {
  offsetParent: Element,
}

export interface InteractEvent {
  target: InteractElement,
  offsetParent: Element,
  x: number,
  y: number,
  clientX: number,
  clientY: number,
}

// Get {x, y} positions from event.
export function getControlPosition (event: InteractEvent) {
  return offsetXYFromParentOf(event)
}

// Get from offsetParent
export function offsetXYFromParentOf (event: InteractEvent) {
  const offsetParent = event.target.offsetParent || document.body
  const offsetParentRect = event.offsetParent === document.body
    ? {
      left: 0,
      top: 0
    }
    : offsetParent.getBoundingClientRect()

  const x = event.clientX + offsetParent.scrollLeft - offsetParentRect.left
  const y = event.clientY + offsetParent.scrollTop - offsetParentRect.top

  return {
    x,
    y
  }
}

// Create an data object exposed by <DraggableCore>'s events
export function createCoreData (lastX: number, lastY: number, x: number, y: number) {
  // State changes are often (but not always!) async. We want the latest value.
  const isStart = !isNum(lastX)

  if (isStart) {
    // If this is our first move, use the x and y as last coords.
    return {
      deltaX: 0,
      deltaY: 0,
      lastX: x,
      lastY: y,
      x: x,
      y: y
    }
  } else {
    // Otherwise calculate proper values.
    return {
      deltaX: x - lastX,
      deltaY: y - lastY,
      lastX: lastX,
      lastY: lastY,
      x: x,
      y: y
    }
  }
}

function isNum (num: unknown) {
  return typeof num === 'number' && !isNaN(num)
}
